/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package main;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Random;

/**
 *
 * @author sbavdhorst
 */
public class GUI extends java.awt.Frame {

    /**
     * Creates new form GUI2
     */
    public GUI() {
        initComponents();
    }
    
    private int size= 0;
    private ArrayList<Quartet> set = null;
    private Circle circle = null;
    private ArrayList[] pairs = null;
    private int attempt = 0;
    private long time = 0;
    private ArrayList<Long> times = new ArrayList<>();
    private int succes = 0;

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        buttonGroup2 = new javax.swing.ButtonGroup();
        buttonGroup3 = new javax.swing.ButtonGroup();
        jPanel1 = new javax.swing.JPanel();
        jTextField1 = new javax.swing.JTextField();
        jTextField2 = new javax.swing.JTextField();
        jRadioButton1 = new javax.swing.JRadioButton();
        jRadioButton2 = new javax.swing.JRadioButton();
        jRadioButton3 = new javax.swing.JRadioButton();
        jTextField3 = new javax.swing.JTextField();
        jRadioButton4 = new javax.swing.JRadioButton();
        jRadioButton5 = new javax.swing.JRadioButton();
        jTextField4 = new javax.swing.JTextField();
        jTextField5 = new javax.swing.JTextField();
        jRadioButton7 = new javax.swing.JRadioButton();
        jTextField6 = new javax.swing.JTextField();
        jCheckBox1 = new javax.swing.JCheckBox();
        jButton1 = new javax.swing.JButton();
        jTextField12 = new javax.swing.JTextField();
        jButton2 = new javax.swing.JButton();
        jRadioButton8 = new javax.swing.JRadioButton();
        jRadioButton9 = new javax.swing.JRadioButton();
        jRadioButton10 = new javax.swing.JRadioButton();
        jRadioButton11 = new javax.swing.JRadioButton();
        jPanel2 = new javax.swing.JPanel();
        jTextField7 = new javax.swing.JTextField();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();
        jTextField8 = new javax.swing.JTextField();
        jTextField9 = new javax.swing.JTextField();
        jTextField10 = new javax.swing.JTextField();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTextArea2 = new javax.swing.JTextArea();
        jTextField11 = new javax.swing.JTextField();
        jScrollPane3 = new javax.swing.JScrollPane();
        jTextArea3 = new javax.swing.JTextArea();

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });

        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jPanel1.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        jTextField1.setBackground(new java.awt.Color(240, 240, 240));
        jTextField1.setFont(jTextField1.getFont());
        jTextField1.setText("Set size:");
        jTextField1.setToolTipText("");
        jTextField1.setBorder(null);
        jTextField1.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField1.setEnabled(false);
        jPanel1.add(jTextField1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 10, -1, -1));

        jTextField2.setBackground(new java.awt.Color(240, 240, 240));
        jTextField2.setText("For every 4 taxa:");
        jTextField2.setToolTipText("");
        jTextField2.setBorder(null);
        jTextField2.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField2.setEnabled(false);
        jPanel1.add(jTextField2, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 50, -1, -1));

        buttonGroup1.add(jRadioButton1);
        jRadioButton1.setText("1 quartet");
        jPanel1.add(jRadioButton1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 70, -1, -1));

        buttonGroup1.add(jRadioButton2);
        jRadioButton2.setText("2 quartets");
        jPanel1.add(jRadioButton2, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 90, -1, -1));

        buttonGroup1.add(jRadioButton3);
        jRadioButton3.setText("1 or 2 quartets");
        jPanel1.add(jRadioButton3, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 110, -1, -1));

        jTextField3.setBackground(new java.awt.Color(240, 240, 240));
        jTextField3.setText("Generation method:");
        jTextField3.setBorder(null);
        jTextField3.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField3.setEnabled(false);
        jPanel1.add(jTextField3, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 140, -1, -1));

        buttonGroup2.add(jRadioButton4);
        jRadioButton4.setText("Random");
        jPanel1.add(jRadioButton4, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 160, -1, -1));

        buttonGroup2.add(jRadioButton5);
        jRadioButton5.setText("Random from circle: ");
        jPanel1.add(jRadioButton5, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 180, -1, -1));

        jTextField4.setText("abcde");
        jTextField4.setPreferredSize(new java.awt.Dimension(100, 20));
        jPanel1.add(jTextField4, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 180, 90, -1));

        jTextField5.setBackground(new java.awt.Color(240, 240, 240));
        jTextField5.setText("Solving method:");
        jTextField5.setBorder(null);
        jTextField5.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField5.setEnabled(false);
        jPanel1.add(jTextField5, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 250, -1, -1));

        buttonGroup3.add(jRadioButton7);
        jRadioButton7.setText("Brute force");
        jPanel1.add(jRadioButton7, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 270, -1, -1));

        jTextField6.setBackground(new java.awt.Color(240, 240, 240));
        jTextField6.setText("Other");
        jTextField6.setBorder(null);
        jTextField6.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField6.setEnabled(false);
        jPanel1.add(jTextField6, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 360, -1, -1));

        jCheckBox1.setText("Save");
        jPanel1.add(jCheckBox1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 380, -1, -1));

        jButton1.setText("Run until solution is found!");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        jPanel1.add(jButton1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 450, 210, -1));

        jTextField12.setText("...");
        jPanel1.add(jTextField12, new org.netbeans.lib.awtextra.AbsoluteConstraints(60, 10, 40, -1));

        jButton2.setText("Run 1000 times!");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });
        jPanel1.add(jButton2, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 470, 210, -1));

        buttonGroup3.add(jRadioButton8);
        jRadioButton8.setText("Constraint programming");
        jRadioButton8.setToolTipText("");
        jRadioButton8.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioButton8ActionPerformed(evt);
            }
        });
        jPanel1.add(jRadioButton8, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 290, -1, -1));

        buttonGroup2.add(jRadioButton9);
        jRadioButton9.setText("Random from random circle");
        jPanel1.add(jRadioButton9, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 200, -1, -1));

        buttonGroup3.add(jRadioButton10);
        jRadioButton10.setText("Greedy solver");
        jRadioButton10.setToolTipText("");
        jPanel1.add(jRadioButton10, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 330, -1, -1));

        buttonGroup3.add(jRadioButton11);
        jRadioButton11.setText("Separated constraint");
        jPanel1.add(jRadioButton11, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 310, -1, -1));

        add(jPanel1, java.awt.BorderLayout.WEST);
        jPanel1.getAccessibleContext().setAccessibleName("ButtonsPanel");
        jPanel1.getAccessibleContext().setAccessibleDescription("");

        jPanel2.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        jTextField7.setBackground(new java.awt.Color(240, 240, 240));
        jTextField7.setText("Quartets:");
        jTextField7.setBorder(null);
        jTextField7.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField7.setEnabled(false);
        jPanel2.add(jTextField7, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 10, -1, -1));

        jTextArea1.setColumns(20);
        jTextArea1.setEditable(false);
        jTextArea1.setRows(5);
        jTextArea1.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextArea1.setEnabled(false);
        jScrollPane1.setViewportView(jTextArea1);

        jPanel2.add(jScrollPane1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 30, 90, 620));

        jTextField8.setBackground(new java.awt.Color(240, 240, 240));
        jTextField8.setText("Circle:");
        jTextField8.setBorder(null);
        jTextField8.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField8.setEnabled(false);
        jPanel2.add(jTextField8, new org.netbeans.lib.awtextra.AbsoluteConstraints(130, 10, -1, -1));

        jTextField9.setText("...");
        jTextField9.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField9.setEnabled(false);
        jPanel2.add(jTextField9, new org.netbeans.lib.awtextra.AbsoluteConstraints(130, 30, 140, -1));

        jTextField10.setBackground(new java.awt.Color(240, 240, 240));
        jTextField10.setText("Pair analysis:");
        jTextField10.setBorder(null);
        jTextField10.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField10.setEnabled(false);
        jPanel2.add(jTextField10, new org.netbeans.lib.awtextra.AbsoluteConstraints(130, 60, -1, -1));

        jTextArea2.setColumns(20);
        jTextArea2.setEditable(false);
        jTextArea2.setRows(5);
        jTextArea2.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextArea2.setEnabled(false);
        jScrollPane2.setViewportView(jTextArea2);

        jPanel2.add(jScrollPane2, new org.netbeans.lib.awtextra.AbsoluteConstraints(130, 80, 140, 570));

        jTextField11.setBackground(new java.awt.Color(240, 240, 240));
        jTextField11.setText("Other info:");
        jTextField11.setBorder(null);
        jTextField11.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextField11.setEnabled(false);
        jPanel2.add(jTextField11, new org.netbeans.lib.awtextra.AbsoluteConstraints(290, 10, -1, -1));

        jTextArea3.setColumns(20);
        jTextArea3.setEditable(false);
        jTextArea3.setRows(5);
        jTextArea3.setDisabledTextColor(new java.awt.Color(0, 0, 0));
        jTextArea3.setEnabled(false);
        jScrollPane3.setViewportView(jTextArea3);

        jPanel2.add(jScrollPane3, new org.netbeans.lib.awtextra.AbsoluteConstraints(290, 30, 220, 620));

        add(jPanel2, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * Exit the Application
     */
    private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
        System.exit(0);
    }//GEN-LAST:event_exitForm

    private void runOnce(){
        //set generation
        if(jRadioButton4.isSelected()){  //random generation
            if (jRadioButton1.isSelected())  // 1 quartet for every 4 taxa
                set = DenseSetGenerator.randomSet(size,1);
            else if (jRadioButton2.isSelected())  // 2 quartet for every 4 taxa
                set = DenseSetGenerator.randomSet(size,2);
            else if (jRadioButton3.isSelected())  // 1 or 2 quartet for every 4 taxa
                set = DenseSetGenerator.randomSet(size,0);
            else
                System.out.println("Radio knop fout!!");
        } else if(jRadioButton5.isSelected()){  // generation from circle
            if(jTextField4.getText().toCharArray().length == size){
                if (jRadioButton1.isSelected())  // 1 quartet for every 4 taxa
                    set = DenseSetGenerator.setFromCircle(size, new Circle(jTextField4.getText().toCharArray()), 1);
                else if (jRadioButton2.isSelected())  // 2 quartet for every 4 taxa
                    set = DenseSetGenerator.setFromCircle(size, new Circle(jTextField4.getText().toCharArray()), 2);
                else if (jRadioButton3.isSelected())  // 1 or 2 quartet for every 4 taxa
                    set = DenseSetGenerator.setFromCircle(size, new Circle(jTextField4.getText().toCharArray()), 0);
                else
                    System.out.println("Radio knop fout bij set van cirkel!!");
            }else
                System.err.println("input circle and input size doesn't match");
        } else if(jRadioButton9.isSelected()){  // generation from circle
                if (jRadioButton1.isSelected())  // 1 quartet for every 4 taxa
                    set = DenseSetGenerator.setFromCircle(size, randomCircle(size), 1);
                else if (jRadioButton2.isSelected())  // 2 quartet for every 4 taxa
                    set = DenseSetGenerator.setFromCircle(size, randomCircle(size), 2);
                else if (jRadioButton3.isSelected())  // 1 or 2 quartet for every 4 taxa
                    set = DenseSetGenerator.setFromCircle(size, randomCircle(size), 0);
                else
                    System.out.println("Radio knop fout bij set van random cirkel!!");
        } else{
            System.out.println("Some other radio button error!");
        }

        //solver selection
        long current = System.currentTimeMillis();
        if(jRadioButton7.isSelected()){
            circle = Solver.bruteForce(set, size);
        } else if(jRadioButton8.isSelected()){
            circle = Solver.constraintProgramming(set, size);
        } else if(jRadioButton10.isSelected()){
            circle = Solver.greedy(set, size);
        } else if(jRadioButton11.isSelected())
            circle = Solver.separatedConstraint(set, size);
        time = System.currentTimeMillis() - current;
        if(!circle.isEmpty()){
            succes++;
        }
    }
    
    private static Circle randomCircle(int size){
        char[] circle = new char[size];
        char[] alphabet = DenseSetGenerator.generateAlphabet(size);
        ArrayList<Integer> numbers = new ArrayList<>();
        Random generator = new Random();
        for(int i = 0; i< size; i++)
            numbers.add(i);
        for(int j = 0; j<size; j++){
            int r = generator.nextInt(numbers.size());
            circle[j] = alphabet[numbers.get(r)];
            numbers.remove(r);
        }
        return new Circle(circle);
    }
    
    //display the found result and do some analysis
    private void display(){
        jTextArea1.setText(makeQuartetString());
        jTextField9.setText(makeCircleString());
        jTextArea2.setText(makePairString());
        jTextArea3.setText(makeOtherString());
    }
    
    //save the results
    private void save(){
        StringBuilder s = new StringBuilder();
        s.append("size");
        s.append(size);
        s.append("attempt");
        s.append(attempt);
        s.append(".txt");
        write(s.toString());
    }
    
    //run until solution is found
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        reset();
        size = Integer.parseInt(jTextField12.getText());
        circle = new Circle(size);
        
        do{
            attempt++;
            runOnce();
            times.add(time);
        }while(circle.isEmpty());
        
        pairs = Analysis.getPairs(size, set);
        display();
        if(jCheckBox1.isSelected())
            save();
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        reset();
        size = Integer.parseInt(jTextField12.getText());
        circle = new Circle(size);
        
        
        for(int i=0; i<1000; i++){
            attempt++;
            runOnce();
            times.add(time);
        }
        
        pairs = Analysis.getPairs(size, set);
        display();
        if(jCheckBox1.isSelected())
            save();
    }//GEN-LAST:event_jButton2ActionPerformed

    private void jRadioButton8ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButton8ActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_jRadioButton8ActionPerformed

    private String makeQuartetString(){
        StringBuilder s = new StringBuilder();
        
        for(Quartet q: set){
            s.append(" ");
            s.append(q);
            s.append('\n');
        }
        
        return s.toString();
    }
    
    private String makePairString(){
        StringBuilder s = new StringBuilder();
        
        if(pairs != null){
            for(int i = 0; i < pairs[0].size(); i++){
                s.append(" ");
                s.append(pairs[0].get(i));
                s.append(pairs[1].get(i));
                s.append(": ");
                s.append(pairs[2].get(i));
                s.append('\n');
            }
        }
        
        return s.toString();
    }
    
    private String makeCircleString(){
        StringBuilder s = new StringBuilder();
        
        s.append(circle);

        return s.toString();
    }
    
    private String makeOtherString(){
        StringBuilder s = new StringBuilder();
        
        s.append("Attempt: ");
        s.append(attempt);
        s.append('\n');
        
        s.append("Number of quartets: ");
        s.append(set.size());
        s.append('\n');
        
        s.append("Average time: ");
        double sum = 0;
        for(Long l: times){
            sum += l.doubleValue();
        }
        s.append(sum / times.size());
        s.append('\n');
        
        s.append("Number of successes: ");
        s.append(succes);
        s.append('\n');

        return s.toString();
    }
    
    //makes the string for the save file
    private String makeWriteString(){
        StringBuilder s = new StringBuilder();
        
        s.append("Circle: ");
        s.append(circle);
        
        s.append("\r\n");
        s.append(" From quartets: ");
        s.append("\r\n");
        for(Quartet q: set){
            s.append(" ");
            s.append(q);
            s.append("\r\n");
        }
        
        if(pairs != null){
            for(int i = 0; i < pairs[0].size(); i++){
                s.append(" ");
                s.append(pairs[0].get(i));
                s.append(pairs[1].get(i));
                s.append(": ");
                s.append(pairs[2].get(i));
                s.append("\r\n");
            }
        }
        
        s.append("Average time: ");
        double sum = 0;
        for(Long l: times){
            sum += l.doubleValue();
        }
        s.append(sum / times.size());
        s.append('\n');
        
        s.append("Number of successes: ");
        s.append(succes);
        s.append('\n');
        
        return s.toString();
    }
    
    private void write(String name){
        try{
            Writer out = new OutputStreamWriter(new FileOutputStream(name));
            try {
                out.write(makeWriteString());
            }
            finally {
                out.close();
            }
        }catch(IOException e){
            System.err.println("Caught IOException: " + e.getMessage());
        }
    }
    
    public void reset(){
        size= 0;
        set = null;
        circle = null;
        pairs = null;
        attempt = 0;
        time = 0;
        times.clear();
        succes =0;
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new GUI().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.ButtonGroup buttonGroup2;
    private javax.swing.ButtonGroup buttonGroup3;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JCheckBox jCheckBox1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JRadioButton jRadioButton1;
    private javax.swing.JRadioButton jRadioButton10;
    private javax.swing.JRadioButton jRadioButton11;
    private javax.swing.JRadioButton jRadioButton2;
    private javax.swing.JRadioButton jRadioButton3;
    private javax.swing.JRadioButton jRadioButton4;
    private javax.swing.JRadioButton jRadioButton5;
    private javax.swing.JRadioButton jRadioButton7;
    private javax.swing.JRadioButton jRadioButton8;
    private javax.swing.JRadioButton jRadioButton9;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JTextArea jTextArea2;
    private javax.swing.JTextArea jTextArea3;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField10;
    private javax.swing.JTextField jTextField11;
    private javax.swing.JTextField jTextField12;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextField3;
    private javax.swing.JTextField jTextField4;
    private javax.swing.JTextField jTextField5;
    private javax.swing.JTextField jTextField6;
    private javax.swing.JTextField jTextField7;
    private javax.swing.JTextField jTextField8;
    private javax.swing.JTextField jTextField9;
    // End of variables declaration//GEN-END:variables
}
